在 TDD 中有個非常重要的部分就是「重構」。
測試的易讀性與易維護性,一直是一個很重要的課題。我們要能透過程式碼的結構及語意,明確傳達出測試的意圖,讓開發者清楚辨別,什麼資訊在這個測試本身是重要的,什麼是不重要的。
例如,在測試檔案 __tests__/post-editor.js
:
fakePost
當中的 title
是不是 'Test Title'
,對這個測試來說並不重要,它只是代表 title
,但它具體是什麼值並不影響測試。
test('renders a form with title, content, tags, and a submit button', async () => {
...
const fakePost = {
title: 'Test Title',
content: 'Test content',
tags: ['tag1', 'tag2'],
}
...
}
我們將重構測試,改成使用工具 test-data-bot 來幫我們自動產生這些資料。
npm install --save-dev @jackfranklin/test-data-bot
或
yarn add --dev @jackfranklin/test-data-bot
引入 'test-data-bot'
中的 build
、 fake
及 sequence
。
tests/post-editor.js
import {build, fake, sequence} from 'test-data-bot'
使用 test-data-bot
產生 post 及 user 的 data:
build()
建立 postBuilder
,並使用 fake()
來產生假的 title、content 跟 tagstests/post-editor.js
const postBuilder = build('Post').fields({
title: fake(f => f.lorem.words()),
content: fake(f => f.lorem.paragraphs().replace(/\r/g, '')),
tags: fake(f => [f.lorem.word(), f.lorem.word(), f.lorem.word()]),
})
因為
.paragraphs()
會在段落開頭產生一行空行,所以需要加上.replace(/\r/g, '')
sequence
產生唯一的 user IDtests/post-editor.js
const userBuilder = build('User').fields({
id: sequence(s => `user-${s}`),
})
將原本的 fakeUser
改為 userBuilder()
, fakePost
改為 postBuilder()
:
tests/post-editor.js
test('renders a form with title, content, tags, and a submit button', async () => {
mockSavePost.mockResolvedValueOnce()
const fakeUser = userBuilder()
const {getByLabelText, getByText} = render(<Editor user={fakeUser} />)
const fakePost = postBuilder()
...
}
另外,如果有 data 對於測試本身是有意義的,也可以傳入值。
例如: postBuilder({content: 'something special'})
,代表 content 的值 'something special'
對測試是有影響的,我們需要它。
const fakePost = postBuilder({content: 'something special'})
但在這個測試,我們不需要這麼做,所以一樣保留 postBuilder()
就好。
完成後,測試應該要亮起綠燈 ✅。
重構之後,我們可以透過測試的程式碼更清楚理解:對於這個測試,user 的值並沒有什麼特別的,post 也是,它們具體是什麼並不影響測試的結果。這可以讓我們更易於維護測試。